package com.seestech.sell.web.api.httpTask;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.seestech.sell.common.annotation.CheckFixedParamValue;
import com.seestech.sell.common.annotation.NotNullParam;
import com.seestech.sell.common.config.ApplicationConfig;
import com.seestech.sell.common.utils.*;
import com.seestech.sell.domain.model.*;
import com.seestech.sell.domain.model.enums.PublishTypeEnums;
import com.seestech.sell.domain.model.enums.StatusEnums;
import com.seestech.sell.service.*;
import com.seestech.sell.service.domessage.DoAgent;
import com.seestech.sell.service.domessage.DoPush;
import com.seestech.sell.web.SuperController;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;


/**
 * Created by idiot on 2017/5/26.
 */
@RestController
@RequestMapping(value = "api/httpTask/agentTask")
public class AgentTask extends SuperController {
    private static Logger logger = LoggerFactory.getLogger(AgentTask.class);

    @Resource
    private DoAgent doAgent;
    @Resource
    private DoPush doPush;
    @Resource
    private IAgentTaskService agentTaskService;
    @Resource
    private IPublishHistoryService publishHistoryService;
    @Resource
    private IAgentService agentService;
    @Resource
    private ApplicationConfig applicationConfig;
    @Resource
    private IFileService fileService;
    @Resource
    private IStatisticsService statisticsService;

    /**
     * myCode执行码
     0  	无任务
     1  	下发任务
     2  	立即关机
     3  	立即重启
     4	    立即截图
     5      终端属性更新
     6      清理任务
     多个任务以;隔开*/


    /**
     * @description  BS获取终端心跳接口
     * @param agentCode
     * @return
     */
    @NotNullParam(params = {"agentCode"})
    @RequestMapping(value = "clientHeartBeat.json")
    public Object getClientHeartBeat(String agentCode){
        logger.info("安卓通讯========>>>>>>>>>>>【心跳接口】======>>>>>>>开始");
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("安卓通讯========>>>>>>>>>>>【心跳接口】======>>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }
        ResultBean<Object> resultBean;
        StringBuffer code = new StringBuffer();  //默认执行码
        // 根据终端的agentCode获取agentId   更新心跳时间
        doAgent.heartBeat(agentCode);
        // 根据当前的agentCode 检测是否有有效任务存在  返回对应的执行码
        AgentTaskInfo agentTask = new AgentTaskInfo();
        agentTask.setStatus(StatusEnums.VALID.getValue());
        agentTask.setAgentCode(agentCode);
        List<AgentTaskInfo> list = agentTaskService.getAgentTasks(agentTask);
        if (list != null && list.size() > 0){
            for (AgentTaskInfo info : list){
                if(code.indexOf(String.valueOf(info.getCode())) < 0){
                    code.append(info.getCode()).append(";");
                }
                //修改为无效
                info.setStatus(StatusEnums.INVALID.getValue());
                agentTaskService.update(info);
            }
        }else
            code.append("0");
        HashMap<String,String> map = new HashMap<>();
        int index = code.lastIndexOf(";");
        map.put("code", index < 0? code.toString() : code.substring(0, index));
        resultBean = ResponseUtils.initResultBean(map, Constants.ResponseCode.success, "成功", true);
        resultBean.setTotalCount(1);
        logger.info("安卓通讯========>>>>>>>>>>>【"+agent.getAgentName()+"心跳接口】======>>>>>>>结果"+resultBean);
        logger.info("安卓通讯========>>>>>>>>>>>【心跳接口】======>>>>>>>结束");
        return resultBean;
    }


    /**
     * @description  BS获取终端属性接口
     * @param agentCode
     * @param ip
     * @param netIp     外网ip
     * @param csNo      终端软件版本号
     * @param hwVer     终端硬件版本号
     * @param os    1:linux 2:windows 3:安卓
     * @param diskCapacity      内存容量
     * @param diskRemaining     内存剩余量
     * @param error     是否异常
     * @param location  经纬度地址
     * @param licenseCode   校验码
     * @param ram      内存容量
     * @param leftRam     内存剩余量
     */
    @NotNullParam(params = {"agentCode", "error"})
    @RequestMapping(value = "clientProperties.json")
    public Object getClientProperties(String agentCode, String ip,
                                      String netIp, String csNo,
                                      String hwVer, Integer os, Long diskCapacity,
                                      Long diskRemaining,
                                      @CheckFixedParamValue(name = "error", value = {"0", "1"}) int error,
                                      String location, String licenseCode,
                                      Long ram, Long leftRam){
        logger.info("安卓通讯========>>>>>>>>>>>【设置终端属性接口】======>>>>>>>开始");
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("安卓通讯========>>>>>>>>>>>【设置终端属性接口】======>>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }
        ResultBean<Object> resultBean = doAgent.setAgentProperties(agent.getAgentId(), ip, netIp, csNo, hwVer, os,
                diskCapacity, diskRemaining, error, location, licenseCode, ram, leftRam);
        logger.info("安卓通讯========>>>>>>>>>>>【"+agent.getAgentName()+"设置终端属性接口】======>>>>>>>结果"+resultBean);
        logger.info("安卓通讯========>>>>>>>>>>>【设置终端属性接口】======>>>>>>>结束");
        return resultBean;
    }


    /**
     * @description  BS获取终端回传截图接口       上传图片  和入库  合并   此接口暂时废弃
     * @param agentCode
     * @param imageName       截图名称
     */
    @Deprecated
    @NotNullParam(params = {"agentCode"})
    @RequestMapping(value = "clientScreenshot.json")
    public Object getScreenshot(String agentCode, String imageName){
        logger.info("安卓通讯========>>>>>>>>>>>【终端回传截图接口】======>>>>>>>开始");
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("安卓通讯========>>>>>>>>>>>【终端回传截图接口】======>>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }
        doAgent.screenshots(agentCode, imageName);
        logger.info("安卓通讯========>>>>>>>>>>>【"+agent.getAgentName()+"终端回传截图接口】======>>>>>>>结束");
        return ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "终端回传截图完成", true);
    }

    /**
     * @description  BS获取下发任务接受率接口
     * @param publishId         发布信息编号
     * @param agentCode
     * @param publishRate          任务接受率
     */
    @NotNullParam(params = {"publishId", "agentCode"})
    @RequestMapping(value = "clientPublishRate.json")
    public Object getPublishRate(String publishId, String agentCode, int publishRate){
        logger.info("安卓通讯========>>>>>>>>>>>【终端下发任务接受率接口】======>>>>>>>开始>>>>>【完成度】"+publishRate);
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("安卓通讯========>>>>>>>>>>>【终端下发任务接受率接口】======>>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }
        doPush.postPublishRate(publishId, agentCode, publishRate);
        logger.info("安卓通讯========>>>>>>>>>>>【"+agent.getAgentName()+"终端下发任务接受率接口】======>>>>>>>结束");
        return ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "更新终端下发任务接受率完成", true);
    }


    /**
     * @description  BS获取任务完成状态接口
     * @param publishId         发布信息编号
     * @param agentCode
     * @param status        是否下发完成 0  否  1 是
     */
    @NotNullParam(params = {"publishId", "agentCode"})
    @RequestMapping(value = "clientPublishEnd.json")
    public Object getPublishEnd(String publishId, String agentCode, String status){
        logger.info("安卓通讯========>>>>>>>>>>>【终端下发任务完成接口】======>>>>>>>开始");
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("安卓通讯========>>>>>>>>>>>【终端下发任务完成接口】======>>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }
        doPush.postPublishEnd(publishId, agentCode, status, DateUtils.formatDatetime(new Date()));
        logger.info("安卓通讯========>>>>>>>>>>>【"+agent.getAgentName()+"终端下发任务完成接口】======>>>>>>>结束");
        return ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "更新终端下发任务完成", true);
    }

    /**
     * 终端下发任务更新完成接口
     * @param publishId
     * @param agentCode
     * @param updateStatus
     * @return
     */
    @NotNullParam(params = {"publishId", "agentCode"})
    @RequestMapping(value = "getUpdateStatus.json")
    public Object getUpdateStatus(String publishId, String agentCode,
                                  @CheckFixedParamValue(name = "updateStatus", value = {"0", "1", "2"})int updateStatus){
        logger.info("安卓通讯========>>>>>>>>>>>【终端下发任务更新完成接口】======>>>>>>>开始");
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("安卓通讯========>>>>>>>>>>>【终端下发任务更新完成接口】======>>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }
        doPush.publishUpdateStatus(publishId, agentCode, updateStatus);
        logger.info("安卓通讯========>>>>>>>>>>>【"+agent.getAgentName()+"终端下发任务更新完成接口】======>>>>>>>结束");
        return ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "终端下发任务更新完成", true);
    }


    /**--------------------------------------*/

    /**
     * @description   终端获取下发任务接口
     * @param agentCode
     * @return
     */
    @NotNullParam(params = {"agentCode"})
    @RequestMapping(value = "publishTask.json")
    public Object publishTask(String agentCode){
        logger.info("安卓通讯========>>>>>>>>>>>【下发终端任务接口】======>>>>>>>开始");
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent == null){
            logger.error("安卓通讯========>>>>>>>>>>>【下发终端任务接口】======>>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }
        ResultBean<Object> resultBean;
        List<HashMap<String, Object>> items = new ArrayList<>();
        PublishHistory info = new PublishHistory();
        info.setStatus(StatusEnums.VALID.getValue());
        info.setAgentCode(agentCode);
        List<PublishHistory> list = publishHistoryService.getPublishHistoriesByInfo(info);
        //组装map
        for (PublishHistory item : list){
            HashMap<String, java.lang.Object> map = new HashMap<>();
            //下发未完成
            if(null == item.getPublishStatus() || 1 != item.getPublishStatus()){
                //判断是否是zip
                if(PublishTypeEnums.ZIP.getValue().equals(item.getType())) {
                    map.put("kind", item.getKind());        //zip下发的类型
                }
                if(PublishTypeEnums.COLUMN.getValue().equals(item.getType())){
                    map.put("index", item.getRemark());     //设置栏目对应的目录
                }
                //判断文件是否存在
                if(FileUtils.existsFile(new File(item.getPath()))) {
                    map.put("priority", item.getPriority());    //优先级
                    map.put("name", item.getPublishName());
                    map.put("publishId", String.valueOf(item.getPublishHistoryId()));
                    map.put("type", item.getType());
                    //文件下载路径
                    map.put("filePath", FileUtils.getTrulyPath(FileUtils.removeBaseDir(applicationConfig.getUploadUrl(), item.getPath())));
                    items.add(map);
                }
            }
        }
        //判断items的大小  如果为空或者大小为0  就返回错误信息
        if(items == null || items.size() < 1){
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无有效下发任务", true);
        }else{
            resultBean = ResponseUtils.initResultBean(items, Constants.ResponseCode.success, "成功", true);
            resultBean.setTotalCount(items.size());
        }
        logger.info("安卓通讯========>>>>>>>>>>>【"+agent.getAgentName()+"下发终端任务接口】======>>>>>>>结果"+resultBean);
        logger.info("安卓通讯========>>>>>>>>>>>【下发终端任务接口】======>>>>>>>结束");
        return resultBean;
    }


    /**
     * @description  终端获取属性接口
     * @param agentCode
     * @return
     */
    @NotNullParam(params = {"agentCode"})
    @RequestMapping(value = "myAgentProperties.json")
    public Object getAgentProperties(String agentCode){
        logger.info("安卓通讯========>>>>>>>>>>>【返回终端属性接口】======>>>>>>>开始");
        ResultBean<Object> resultBean;
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent != null){
            HashMap<String, Object> map = new HashMap<>();
            map.put("volume", agent.getVolume());
            map.put("beatFrequency", agent.getBeatFrequency());
            map.put("startTime", agent.getStartTime());
            map.put("endTime", agent.getEndTime());
            map.put("screenshotFrequency", agent.getScreenshotFrequency());
            map.put("operatePassword", agent.getOperatePassword());             //操作密码
            map.put("location", agent.getLocation());                           //gps定位地址
            map.put("screenMode", agent.getScreenMode());                       //终端屏幕
            map.put("licenseCode", agent.getLicenseCode());                     //许可证
            resultBean = ResponseUtils.initResultBean(map, Constants.ResponseCode.success, "成功", true);
            logger.info("安卓通讯========>>>>>>>>>>>【"+agent.getAgentName()+"返回终端属性接口】======>>>>>>>结果"+resultBean);
        }else {
            logger.error("安卓通讯========>>>>>>>>>>>【返回终端属性接口】======>>>>>>>无效的参数agentCode"+agentCode);
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "无效的参数agentCode", false);
        }
        logger.info("安卓通讯========>>>>>>>>>>>【返回终端属性接口】======>>>>>>>结束");
        return resultBean;
    }


    /**
     * @description 远程接口  添加安卓端的任务
     * @param info
     * @return
     */
    @Deprecated
    @RequestMapping(value = "remoteAddTask.do")
    public Object remoteAddTask(AgentTaskInfo info){
        logger.info("【远程添加安卓任务接口】=======>>>>>>【开始】");
        agentTaskService.insert(info);
        logger.info("【远程添加安卓任务接口】=======>>>>>>【结束】");
        return ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "成功", true);
    }

    /**
     * @description 上传图片  截图图片
     * @param agentCode
     * @return
     */
    @NotNullParam(params = {"agentCode"})
    @RequestMapping(value = "uploadImage.json")
    public Object uploadImage(String agentCode){
        logger.info("【上传截图图片接口】=======>>>>>>【开始】");
        //获取终端信息  拿到图片存储地址
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent != null){
            //监控墙文件夹  对应终端编号
            String path = FileUtils.addPathSeparate(applicationConfig.getBaseDirectory(), Constants.Regular.monitor_wall, agent.getAgentCode());
            //保证 文件夹存在
            File fileDir = FileUtils.buildFileByPath(path);

            //新文件名
            String newFileName;
            //获取图片信息  存储
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request_local.get();
            MultipartFile multipartFile = multiRequest.getFile("image");

            //取得当前上传文件的文件名称
            String myFileName = multipartFile.getOriginalFilename();

            //获取文件拓展名
            String extName = FileUtils.getExtName(myFileName);
            //根据拓展名获取文件类型
            int fileType = FileUtils.getFileTypeByExtName(extName);
            if(fileType == -1 || fileType != 2){
                logger.error("上传文件失败======>【原因】：文件拓展名检测不符合");
                return ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "上传失败，文件后缀不符合", false);
            }
            //重命名文件
            newFileName = System.currentTimeMillis()+StringUtils.randomValue(10000)+"."+extName;

            File file = new File(fileDir, newFileName);
            //拷贝文件流  到上面的文件
            FileUtils.copyInputStreamToFile(multipartFile, file);
            //新增截图信息到数据库
            doAgent.screenshots(agentCode, newFileName);
            logger.info("上传截图图片接口=======>>>>>【"+agent.getAgentName()+"】======>>>>>");
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "上传图片成功", true);
        }else{
            logger.error("【上传截图图片接口】=======>>>>>>无效的参数agentCode"+agentCode);
            return ResponseUtils.initResultBean(null, Constants.ResponseCode.invalid_param, "无效的参数agentCode", false);
        }
    }

    /**
     * 根据文件名称获取文件信息
     * @param fileName
     * @return
     */
    @RequestMapping(value = "getFileByFileName.json")
    @NotNullParam(params = {"fileName"})
    public Object getFileByFileName(String fileName){
        logger.info("根据文件名称获取文件信息================>>>>>>>>开始");
        ResultBean<Object> resultBean;
        FileInfo info = new FileInfo();
        info.setFileName(fileName);
        info.setStatus(StatusEnums.VALID.getValue());
        List<FileInfo> fileInfos = fileService.getFilesByFileInfo(new RowBounds(0, 1), info);
        if(fileInfos != null && fileInfos.size() > 0){
            resultBean = ResponseUtils.initResultBean(fileInfos.get(0), Constants.ResponseCode.success, "成功", true);
            resultBean.setTotalCount(1);
        }else {
            logger.error("不存在该文件=============>>>>");
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.error, "失败", false);
        }
        logger.info("根据文件名称获取文件信息================>>>>>>>>结束");
        return resultBean;
    }


    /**
     * 新增统计数据接口 播放率 点击率
     * json字符串 "data": "{"agentCode": "123456", "type": 1, "items": [{"name":"1","tapArea":"2", "time": 3}]}"
     * @param data
     * @return
     */
    @RequestMapping(value = "addStatistics.json")
    public Object addStatistics(String data){
        logger.info("新增统计数据接口===================>>>>>>>>【开始】");
        ResultBean<Object> resultBean;
        //获取字符串   转换JSONObject
        JSONObject object = JSON.parseObject(data);
        //从 JSONObject  获取agentCode
        String agentCode = object.getString("agentCode");
        //根据获取的agentCode  加载agent信息   判断是否为空
        Agent agent = agentService.getAgentByAgentCode(agentCode);
        if(agent != null){
            //获取添加的数据
            int type = object.getIntValue("type");
            List<Statistics> array = JSON.parseArray(object.getString("items"), Statistics.class);
            if(array != null && array.size() > 0){
                //遍历集合 封装成List<Statistics>  添加主键
                for (Statistics item : array){
                    item.setId(IdGen.get().nextId()); //设置主键
                    item.setCreateTime(new Date());   //创建时间
                    item.setType(type);               //类型
                }
                //批量新增
                statisticsService.insertBatch(array);
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.success, "成功", true);
                logger.info("新增统计数据接口=========="+agent.getAgentName()+"=========>>>>>>>>【结果】"+resultBean);
            }else {
                logger.error("新增统计数据接口===================>>>>>>>>无效的参数items");
                resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.invalid_param, "无效的参数items", false);
            }
        }else {
            logger.error("新增统计数据接口===================>>>>>>>>无效的参数agentCode"+agentCode);
            resultBean = ResponseUtils.initResultBean(null, Constants.ResponseCode.invalid_param, "无效的参数agentCode", false);
        }
        logger.info("新增统计数据接口===================>>>>>>>>【结束】");
        return resultBean;
    }

}
